eBPFLAB 专注eBPF创新技术 您所在的位置:网站首页 ebpf uprobe原理 eBPFLAB 专注eBPF创新技术

eBPFLAB 专注eBPF创新技术

2024-07-14 23:34| 来源: 网络整理| 查看: 265

介绍

USDT全称是Userland Statically Defined Tracing用户态静态定义追踪。

USDT类似内核态的tracepoint,是静态打桩埋点方式。

USDT在很多开源软件,如MySQL、PostgreSQL、Ruby、Python 和Node.js等都有广泛的应用。

工作原理

首先开发人员将通过DTRACE_PROBE相关宏在程序开发过程中植入跟踪点,也就是所谓的埋点。

其次在编译程序的时候,编译器会在目标二进制文件的ELF的.note.stapstd段部分中压制USDT追踪点。

编译器和追踪工具之间规定,USDT的元数据所在的.note.stapstd段必须存在。

这里的note section, 是ELF文件的一个段,以某种方式标记文件的信息,这个在后续的linux内核专题系列中会讲解。对内核感兴趣的朋友,记得关注,不要错过。

最后USDT跟踪工具会对ELF部分进行自检,并在跟踪点的位置替换为int 3中断。当执行到跟踪点的标记处的指令时,会触发中断处理程序,并在内核中调用与uprobe关联的程序来处理事件并将它们发送到用户空间处理。

详细处理可参考上篇的uprobe文章。

以上便是使用USDT的工作原理和使用流程。

实际中我们也许不是程序的开发和维护者,需要跟踪调试的时候,也许该程序已经包含了USDT探测点,或者没有,此时我们需要做个检查。

通过上面工作原理描述,我们知道加了USDT程序埋点会出现在ELF文件的.note.stapstd段,那么我们便可以借助readelf工具来检查是否支持USDT。

实验

安装 systemtap-sdt-dev

# apt-get -y install systemtap-sdt-dev

编译实例程序

#include #include #include int main(int argc, char ** argv) { struct timeval tv; for(int x; x < 1024; x++) { gettimeofday(&tv, NULL); DTRACE_PROBE2(test_app, test_probe, tv.tv_sec, x); sleep(1); } return 0; }

查看.note.stapsdt段信息,可以看到有埋点的详细信息Displaying notes found in: .note.stapsdt。

# readelf -n a.out Displaying notes found in: .note.gnu.property Owner Data size Description GNU 0x00000020 NT_GNU_PROPERTY_TYPE_0 Properties: x86 feature: IBT, SHSTK x86 ISA needed: x86-64-baseline Displaying notes found in: .note.gnu.build-id Owner Data size Description GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring) Build ID: 50d9916129f0b28c92defa0c5a1368ae731e42a0 Displaying notes found in: .note.ABI-tag Owner Data size Description GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag) OS: Linux, ABI: 3.2.0 Displaying notes found in: .note.stapsdt Owner Data size Description stapsdt 0x00000041 NT_STAPSDT (SystemTap probe descriptors) Provider: test_app Name: test_probe Location: 0x00000000000011c2, Base: 0x0000000000002004, Semaphore: 0x0000000000000000 Arguments: -8@%rax -4@-36(%rbp) g#

查看汇编代码,可以发现DTRACE_PROBE2被替换为了NOP指令。

# objdump -d a.out 0000000000001189 : 1189: f3 0f 1e fa endbr64 118d: 55 push %rbp 118e: 48 89 e5 mov %rsp,%rbp 1191: 48 83 ec 40 sub $0x40,%rsp 1195: 89 7d cc mov %edi,-0x34(%rbp) 1198: 48 89 75 c0 mov %rsi,-0x40(%rbp) 119c: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 11a3: 00 00 11a5: 48 89 45 f8 mov %rax,-0x8(%rbp) 11a9: 31 c0 xor %eax,%eax 11ab: eb 24 jmp 11d1 11ad: 48 8d 45 e0 lea -0x20(%rbp),%rax 11b1: be 00 00 00 00 mov $0x0,%esi 11b6: 48 89 c7 mov %rax,%rdi 11b9: e8 c2 fe ff ff call 1080 11be: 48 8b 45 e0 mov -0x20(%rbp),%rax 11c2: 90 nop 11c3: bf 01 00 00 00 mov $0x1,%edi 11c8: e8 c3 fe ff ff call 1090 11cd: 83 45 dc 01 addl $0x1,-0x24(%rbp) 11d1: 81 7d dc ff 03 00 00 cmpl $0x3ff,-0x24(%rbp) 11d8: 7e d3 jle 11ad 11da: b8 00 00 00 00 mov $0x0,%eax 11df: 48 8b 55 f8 mov -0x8(%rbp),%rdx 11e3: 64 48 2b 14 25 28 00 sub %fs:0x28,%rdx 11ea: 00 00 11ec: 74 05 je 11f3 11ee: e8 7d fe ff ff call 1070 11f3: c9 leave 11f4: c3 ret

增加探测点,我们这次使用tracing的一个前端工具perf跟ftrace做个对比。

使用perf工具

# perf buildid-cache --add ./a.out # perf list |grep sdt sdt_test_app:test_probe [SDT event] # perf probe --add=sdt_test_app:test_probe Added new event: sdt_test_app:test_probe (on %test_probe in /code/tracing/a.out) You can now use it in all perf tools, such as: perf record -e sdt_test_app:test_probe -aR sleep 1

通过ftrace的debugfs接口查看,已经有uprobe event了,也就是perf工具增加的探测点事件。

cat /sys/kernel/debug/tracing/uprobe_events p:sdt_test_app/test_probe /code/tracing/a.out:0x00000000000011c2 arg1=%ax:s64 arg2=-36(%bp):s32

统计探测的事件记录,之前工作中都是源码编译的perf,这里偷懒从官方源下载了perf。perf record时遇到了一个问题,属于官方源的一个坑。在后续的可观测性工具篇幅中详细讲解。

# perf record -e sdt_test_app:test_probe -p $(pidof ./a.out) sleep 10 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.013 MB perf.data (10 samples) ]

查看record报告

# perf script a.out 13209 [000] 135040.744146: sdt_test_app:test_probe: (55ca15c371c2) arg1=1699891733 arg2=845 a.out 13209 [000] 135041.744866: sdt_test_app:test_probe: (55ca15c371c2) arg1=1699891734 arg2=846 a.out 13209 [000] 135042.746374: sdt_test_app:test_probe: (55ca15c371c2) arg1=1699891735 arg2=847 a.out 13209 [000] 135043.746716: sdt_test_app:test_probe: (55ca15c371c2) arg1=1699891736 arg2=848 a.out 13209 [000] 135044.749240: sdt_test_app:test_probe: (55ca15c371c2) arg1=1699891737 arg2=849 a.out 13209 [000] 135045.750033: sdt_test_app:test_probe: (55ca15c371c2) arg1=1699891738 arg2=850 a.out 13209 [000] 135046.750779: sdt_test_app:test_probe: (55ca15c371c2) arg1=1699891739 arg2=851 a.out 13209 [000] 135047.751260: sdt_test_app:test_probe: (55ca15c371c2) arg1=1699891740 arg2=852 a.out 13209 [000] 135048.751595: sdt_test_app:test_probe: (55ca15c371c2) arg1=1699891741 arg2=853 a.out 13209 [000] 135049.753703: sdt_test_app:test_probe: (55ca15c371c2) arg1=1699891742 arg2=854

操作ftrace的debugfs接口

增加探测点

# echo 'p:test_usdt ./a.out:0x11c2' > /sys/kernel/debug/tracing/uprobe_events 0x11c2 即实例程序反汇编看到的nop指令地址,也就是增加的埋点处地址。

激活探测点

# echo 1 > /sys/kernel/debug/tracing/events/uprobes/test_usdt/enable

查看trace

# cat /sys/kernel/debug/tracing/trace # tracer: nop # # entries-in-buffer/entries-written: 4/4 #P:2 # # _-----=> irqs-off/BH-disabled # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / _-=> migrate-disable # |||| / delay # TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | a.out-19260 [000] DNZff 136227.665453: test_usdt: (0x560ec73191c2) a.out-19260 [000] DNZff 136228.666249: test_usdt: (0x560ec73191c2) a.out-19260 [000] DNZff 136229.666713: test_usdt: (0x560ec73191c2) a.out-19260 [000] DNZff 136230.669335: test_usdt: (0x560ec73191c2)

可以看到使用前端工具与操作ftrace的debugfs是一样的效果,这些前端工具方便做跟踪操作,提高效率。

前端工具有很多,后面会调几个介绍如何使用。关注公众号,不要错过。

参考

https://www.brendangregg.com/blog/2015-06-28/linux-ftrace-uprobe.html https://installati.one/install-systemtap-sdt-dev-ubuntu-22-04/ https://www.openvswitch.org/support/ovscon2021/slides/debugging_using_tracepoints.pdf https://medium.com/@yunwei356/ebpf-tutorial-by-example-15-capturing-user-space-java-gc-event-duration-using-usdt-46436f772ce8 https://docs.openvswitch.org/en/latest/topics/usdt-probes/ https://www.openvswitch.org/support/ovscon2021/slides/debugging_using_tracepoints.pdf https://bugs.archlinux.org/task/77826 https://docs.frrouting.org/projects/dev-guide/en/latest/tracing.html https://opeonikute.dev/posts/observing-node-with-ebpf https://lists.iovisor.org/g/iovisor-dev/topic/how_to_use_usdt_probes/21386285 https://docs.rs/usdt/latest/usdt/ https://www.brendangregg.com/blog/2015-07-03/hacking-linux-usdt-ftrace.html

欢迎大家转发分享。未经授权,严禁任何复制、转载、摘编或以其它方式进行使用,转载须注明来自eBPFLAB并附上本文链接。如果有侵犯到您权益的地方,请及时联系我删除。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有